package ch.bfh.java.directorysynchronizer.presentation.Frame;

import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;

import difflib.Delta;
import difflib.DiffUtils;
import difflib.Patch;

public class FileDiffDialog extends JDialog
{
	public enum Response {
		CANCEL,
		OVERWRITE,
		SKIP
	}
	
	private static final long serialVersionUID = 8786878304635594282L;
	private boolean remember = false;
	private Response response = Response.CANCEL;
	
	
	public FileDiffDialog(JFrame parent, final File source, final File target)
	{
		super(parent, true);
		setTitle("File conflict occurred");
		
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
		addWindowListener(new WindowAdapter() {
		      public void windowClosing(WindowEvent we) {
		        setVisible(false);
		      }
		    });
		
		setAlwaysOnTop(true);
		setSize(new Dimension(400, 600));
		
		Date sourceDate = new Date(source.lastModified());
		Date targetDate = new Date(target.lastModified());
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
		
		String fileInfo = 
			"<html>" +
				"<table>" +
					"<tr><td colspan=2><b>Source file<b></td>" + 
					"<tr><td>Path:</b></td><td>" + source.getAbsolutePath() + "</td></tr>" +
					"<tr><td>Last modified:</td><td>" + simpleDateFormat.format(sourceDate) + "</td></tr>" +
					"<tr><td>Size:</td><td>" + source.length() + " Bytes</td></tr>" +
					"<tr><td></td><td></td>" +
					"<tr><td colspan=2><b>Target file<b></td>" + 
					"<tr><td>Path:</b></td><td>" + target.getAbsolutePath() + "</td></tr>" +
					"<tr><td>Last modified:</td><td>" + simpleDateFormat.format(targetDate) + "</td></tr>" +
					"<tr><td>Size:</td><td>" + target.length() + " Bytes</td></tr>" +
				"</table>" +
			"</html>";
					
		
		setLayout(new FlowLayout());
		getContentPane().add(new JLabel(fileInfo));
		final JButton showDiffButton = new JButton("Show difference between files");
		final JButton overwriteButton = new JButton("Overwrite");
		final JButton skipButton = new JButton("Skip");
		JButton cancelButton = new JButton("Cancel");
				
		ActionListener al = new ActionListener() {
			@Override
            public void actionPerformed(ActionEvent event)
            {
	            if(event.getSource() == overwriteButton)
	            {
	            	response = Response.OVERWRITE;
	            	setVisible(false);
	            }
	            else if(event.getSource() == skipButton)
	            {
	            	response = Response.SKIP;
	            	setVisible(false);
	            }
	            else if(event.getSource() == showDiffButton)
	            {
	            	JLabel diffLabel = new JLabel(getDiffString(source, target));
	            	diffLabel.setFont(new Font("Monospaced", Font.PLAIN, 10));
	            	JOptionPane.showMessageDialog(null, diffLabel);
	            }
	            else
	            {
	            	response = Response.CANCEL;
	            	setVisible(false);
	            }
            }
		};
		
		showDiffButton.addActionListener(al);
		overwriteButton.addActionListener(al);
		skipButton.addActionListener(al);
		cancelButton.addActionListener(al);
		
		JCheckBox rememberCheckBox = new JCheckBox("Apply decision for all items", false);
		
		ItemListener il = new ItemListener()
		{
			@Override
			public void itemStateChanged(ItemEvent e)
			{
				remember = e.getStateChange() == ItemEvent.SELECTED;				
			}
		};
		
		rememberCheckBox.addItemListener(il);

		getContentPane().add(showDiffButton);
		
		getContentPane().add(rememberCheckBox);
		getContentPane().add(overwriteButton);
		getContentPane().add(skipButton);
		getContentPane().add(cancelButton);
		
		pack();
	}

	private String getDiffString(File source, File target)
    {
		List<String> original = fileToLines(source);
        List<String> revised  = fileToLines(target);
        
        Patch patch = DiffUtils.diff(original, revised);

        StringBuffer sb = new StringBuffer("<html><div align=left>");
        
        for (Delta delta: patch.getDeltas()) {
        	for (Object line : delta.getOriginal().getLines()) {
                sb.append("-" + line + "<br>");
            }
            for (Object line : delta.getRevised().getLines()) {
            	sb.append("-" + line + "<br>");
            }        	
        }

        return sb.append("</div></html>").toString();
    }
	
	/**
	 * Copied code from http://code.google.com/p/java-diff-utils/wiki/SampleUsage
	 */
	private static List<String> fileToLines(File file)
	{
		List<String> lines = new LinkedList<String>();
		String line = "";
		try
		{
			BufferedReader in = new BufferedReader(new FileReader(file));
			while((line = in.readLine()) != null)
			{
				lines.add(line);
			}
		}
		catch(IOException e)
		{
			e.printStackTrace();
		}
		return lines;
	}


	public Response getResponse()
	{
		return response;
	}
	
	public boolean getRemember()
	{
		return remember;
	}
}
